今天這篇會先介紹 v-on 的語法和修飾符,熟悉的人可以考慮跳過這個部份。
再來會提到自己在學習 v-on 時的疑惑:
console.log?」如果你也很好奇,就一起來看看吧! (不好奇的話就跳過吧哈哈)
最後會補充 .passive 修飾符,這個修飾符對應到 addEventListener 的 passive option,是我自己之前比較陌生的部份!
v-on 快速通關:語法簡介console.log
console.log
app.config.globalProperties 自定義所有模板都可以取到的全域屬性.passive 修飾符v-on 快速通關
v-on:
v-on 指令是用來為元素綁定事件監聽器v-on 的部份可以縮寫為 @。Argument
type 屬性,鍵的名稱可以參考 MDN - Events
emit 來發送自定義事件Modifiers
Vue 針對常用的事件邏輯處理,提供對應的修飾符(modifier),開發者不用一直寫重複的程式碼,也讓 handler 內的程式碼變得更簡潔,並且修飾符可以串接使用。
.stop:阻止事件冒泡,相當於 event.stopPropagation()
.prevent:取消事件的預設行為,相當於 event.preventDefault()
.self:只在綁定監聽器的元素&觸發監聽器的元素相等才執行,即 event.target === event.currentTarget
還有對應到 addEventListener 三個 option 的修飾符:
addEventListener(type, listener, options = {
capture: true,
once: true,
passive: true,
})
.capture: 切換成捕獲模式(capture).once:只觸發一次,觸發後就自動移除監聽.passive:告訴瀏覽器這個 handler 內不會呼叫 event.preventDefault(),通常用在 touch 相關的事件,可以讓行動裝置上的頁面滑動更流暢;不可以和 .prevent 修飾符同時使用。(發現自己對 .passive 並不熟悉,這部份補充在最後)按鍵修飾符:監聽鍵盤相關事件時,通常需要確認使用的按鍵,在 Vue 可以透過 Key modifier 做到,鍵的名稱可以參考 MDN - Key values for keyboard events。
針對常用的按鍵提供別名:
.enter
.tab
.delete (包含 "Delete" 和 "Backspace").esc
.space
.up
.down
.left
.right
系統鍵修飾符:和一般按鍵不同,事件觸發時,系統鍵必須處於按下的狀態,通常會跟其他按鍵組合使用。
.ctrl
.alt
.shift
.meta
滑鼠按鍵修飾符:.left、.right、.middle 可以配合 mouseEvent 使用。
嚴格修飾符 .exact:想要嚴格符合設定才會觸發事件,可以使用 .exact 來做修飾,以 click 為例:
@click.exact : 什麼按紐都不按點擊按鈕才會觸發事件。@click : 在點擊時按住任何按鈕都會觸發事件。Valuev-on 根據綁定的 value 不同分為兩種:
<button @click="warn">
Submit
</button>
function warn(event) {
// 可以取到原生的 event 物件
if (event) {
event.preventDefault()
}
window.alert("現在還不能送出");
}
<button @click="count++">+1</button>
<button @click="userInput = ''">Reset</button>
function warn(message, event) {
// 可以取到原生的 event 物件
if (event) {
event.preventDefault()
}
alert(message)
}
$event
<button @click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
event
<button @click="(event) => warn('Form cannot be submitted yet.', event)">
Submit
</button>
console.log在 Vue 模板測試 v-on event handler,如:在父元件監聽子元件 emit 事件時,會很直覺想用 inline handler 搭配 console.log() 去印東西,確認有監聽到事件。
像這樣:
<template>
<button @click="console.log('點擊了按鈕')">按鈕</button>
</template>
或是這樣:
<template>
<BaseInput
:modelValue="userName"
@update:modelValue="console.log('輸入了名字')"
/>
</template>
結果就是收到無數的報錯QQ
像這樣:
這是因為 Vue 預設 template 中的表達式只能使用部份的全域物件,例如:Number, Array, Math, Date 等等,其中不包括 console 跟 window!
所以每次在 template 讀到 console.log 時, Vue 無法取用到全域的 console,它會在元件內部找尋 console 這個變數,所以相關報錯通常會是無法讀取 undefined(reading 'log')。
同理,在 Vue 預設的情境下,我們也沒辦法在 template 調用 window.alert(),或 window 底下相關的變數或函式。
但我們可以透過 app 實例調整設定,做法很簡單。
最後附上 Vue template 可以使用的完整 global 清單如下: 原始碼連結
const GLOBALS_WHITE_LISTED =
'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +
'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt'
console.log我們可以透過 app.config.globalProperties 將 console 註冊為所有元件實例都可以取用到的全域物件。
在 main.js 中加入這段程式碼,就可以在所有 Vue template 中使用 console.log。
app.config.globalProperties.console = console;
記得要在 app 實例建立之後,才可以透過 .config 去設定。
const app = createApp(App);
app.config.globalProperties.console = console;
app.mount("#app");
Vue.property 去設定全域屬性。.passive 修飾符.passive 修飾符會對應到 addEventListener 的 passive option (預設值為 false):
addEventListener(type, listener, {
passive: true,
})
將 passive 選項設置為 true 就是在告訴瀏覽器:這個事件 handler 裡面不會呼叫 event.preventDefault(),你可以直接響應預設行為。
這樣有什麼好處?
可以優化效能,提昇使用者體驗。
因為瀏覽器事先不知道 handler 裡面是否會呼叫 event.preventDefault() 來阻止預設行為,所以瀏覽器需要先執行一次 handler,花時間確定裡面有沒有呼叫 event.preventDefault() ,才決定是否要響應預設行為。
適合拿來優化高頻率觸發的事件監聽器,例如:手機的 touch 事件,瀏覽器就不用在每次使用者開始滑動的時候,花時間重新確認 handler 裡面是否呼叫 event.preventDefault(),導致滑動上的微卡頓。
passive option根據 MDN 的說法,除了 Safari 和 IE,其他多數瀏覽器已經將 Window、Document 和 Document.body 在 wheel、mousewheel、touchstart 和 touchmove 事件監聽中 passive 選項預設為 true。
那 scroll 事件呢?這個事件感覺也很適合使用 passive。
The basic scroll event cannot be canceled, so it does not need to be set passive.
scroll 事件的預設行為本身是不能取消的,所以不需要對這類事件監聽器啟用 passive 選項。
想知道 .passive 修飾符的作用可以看以下資料:
EventTarget.addEventListener()